home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / comm / comm5 / nwsbrkr5.lha / Reader / NewsBreaker / src / gui / Boopsi.c next >
C/C++ Source or Header  |  1996-12-15  |  14KB  |  503 lines

  1. /*
  2.  * Boopsi.c -- BOOPSI Objekte anlegen und entfernen
  3.  *
  4.  */
  5.  
  6.  
  7. /*
  8.    Gadgetklassen-Bezeichner. Mit diesem Namen wird die public BOOPSI Klasse
  9.    gefunden. Wäre die Klasse privat, würde ein Pointer auf sie (statt Name)
  10.    verwendet.
  11.  */
  12.  
  13. #define NB_BUTTONCLASSNAME "button.gadget"
  14. char *buttonClassName = NB_BUTTONCLASSNAME;
  15.  
  16. /*
  17.    Entwurf einer BOOPSI-Objekt-Liste
  18.  
  19.    Node:
  20.  
  21.    BoopsiObject
  22.    {
  23.    Node      bo_node    --- Standard Exec Node mit Name, Type, Pri Feld
  24.  
  25.    --------------------- Nutzdaten -------------------------
  26.  
  27.    Object *  bo_object  --- zeigt auf Adresse der Objekt-INSTANZ,
  28.  
  29.    NULL: kein Objekt vorhanden
  30.    !NULL: (gültiges?) Objekt ist vorhanden
  31.  
  32.  
  33.    Begriffe: Instanz -- Klasse
  34.    "Diese Instanz A wurde aus der Klasse X erzeugt."
  35.    "Diese Klasse X hat die Instanzen A, B und C erzeugt."
  36.  
  37.    Instanz = konkretes, erzeugtes Objekt: A, B, C.
  38.    Klasse  = X, "Schöpfer"(Ausdruck!) für Instanzen.
  39.  
  40.  
  41.    USHORT    bo_type    --- Gadget/Image/Listview Item/Pseudoeintrag
  42.    LONGBITS  bo_status  --- BITS
  43.    active
  44.    valid
  45.    ..
  46.  
  47.    }
  48.  
  49.    2. eine Struktur KeyboardObject
  50.  
  51.    Problem: Tastatureingaben dynamisch auswerten
  52.  
  53.    Lösungsmöglichkeit:
  54.    - spezielle Exec Liste aus KeyboardObjects.
  55.    - eine spezielle Routine, die in der IDCMP Schleife ist:
  56.    - empfängt Tastendruck (keyboard event)
  57.    - geht List-Nodes durch und vergleicht pro Node:
  58.    - ist
  59.    IMsg.Code/.Qualifier == KeyboardObject.kb_code/.kb_qualifier
  60.  
  61.    -- wenn ja:
  62.    --- löse aus Aktion
  63.    ---- ist
  64.    --- breche ab Node-Durchlauf
  65.  
  66.    (-- wenn nein:
  67.    --- weiter mit nächstem Node bis Listenende)
  68.  
  69.  
  70.  
  71.    Node
  72.  
  73.    KeyboardObject
  74.    {
  75.    struct Node kb_node;
  76.    ULONG(?)    kb_code;        -- wie IMsg-Feld: einfacher Tastendruck
  77.    ULONG(?)    kb_qualifier;   -- wie IMsg-Feld: Zusatztaste z.B. Shift usw.
  78.    ULONG       kb_bobject;     -- Adresse des zugehörigen BOOPSI Objekt*Node*!.
  79.    !NULL: Bei Tastendruck bekommt Objekt IM_DRAW
  80.    Messages Activated, Normal.
  81.    --> immer vorab Test ob gültiger Node
  82.    NULL: kein Boopsi Objekt ist dem Tastendruck
  83.    zugeordnet.
  84.    APTR        kb_userdata    --  wie in Gadget.UserData/Menu.User.Data:
  85.    zur Zeit noch (APTR) actioncode.
  86.    Siehe <src/Actioncode.h> für Infos über das 
  87.    Actioncode-System
  88.    später: (todo) Zeiger auf erweiterte
  89.    Actioncode-Struktur, als Input für
  90.    typenfreie(?) Parameterübergabe im ReadArgs
  91.    Template.
  92.    }
  93.  
  94.  */
  95.  
  96. /* todo Gadget IDs */
  97. #define    GID_Naechste    0
  98. #define    GID_Vorherige    1
  99. #define    GID_Messages    2
  100. #define GID_Gruppen    3
  101. #define GID_CatchUp     4
  102. #define    GID_Hilfe       5
  103. #define    NUMGADS         6
  104. struct Gadget *gads[NUMGADS];    /* Namenkonflikt mit BOOPSI ListView vorprogrammiert!!! */
  105.  
  106. /*****************************************************************************/
  107.  
  108. static void
  109. creategads (struct Window *win)
  110. {
  111.   BOOL okay = FALSE;
  112.   LONG x, y, w, h, wspace;
  113.   struct RastPort *rp;
  114.   STRPTR label;
  115.  
  116.  
  117.  
  118.   /* Erzeuge verknüpfte Boopsi-Objekte */
  119.   prop_object = NewObject (NULL, "propgclass",
  120.                GA_ID, 2,
  121.         GA_Top, Mywindow->BorderTop + 2 * gap_h + infobar_h + box_h,
  122.                GA_RelHeight, -(Mywindow->BorderTop + 2 * Mywindow->BorderBottom + 4 * gap_h + infobar_h + box_h),
  123.                GA_RelRight, -(Mywindow->BorderRight - 5),
  124.                GA_Width, Mywindow->BorderRight - 8,
  125.                GA_RightBorder, TRUE,
  126.                ICA_MAP, prop2text,
  127.                ICA_TARGET, NULL,
  128.                PGA_NewLook, TRUE,
  129.                PGA_Borderless, TRUE,
  130.                PGA_Visible, 50,
  131.                PGA_Total, 50,
  132.                TAG_END);
  133.  
  134.   up_image = NewObject (NULL, "sysiclass",
  135.             SYSIA_DrawInfo, dri,
  136.             SYSIA_Which, UPIMAGE,
  137.             IA_Width, Mywindow->BorderRight,
  138.             IA_Height, Mywindow->BorderBottom,
  139.             TAG_END);
  140.  
  141.   down_image = NewObject (NULL, "sysiclass",
  142.               SYSIA_DrawInfo, dri,
  143.               SYSIA_Which, DOWNIMAGE,
  144.               IA_Width, Mywindow->BorderRight,
  145.               IA_Height, Mywindow->BorderBottom,
  146.               TAG_END);
  147.  
  148.   up_object = NewObject (NULL, "buttongclass",
  149.              GA_RelBottom, -(3 * Mywindow->BorderBottom) - 1,
  150.              GA_RelRight, -(Mywindow->BorderRight - 1),
  151.              GA_Height, Mywindow->BorderBottom,
  152.              GA_Width, Mywindow->BorderRight,
  153.              GA_Image, up_image,
  154.              GA_RightBorder, TRUE,
  155.              GA_Previous, prop_object,
  156.              ICA_MAP, up2text,
  157.              TAG_END);
  158.  
  159.   down_object = NewObject (NULL, "buttongclass",
  160.                GA_RelBottom, -(2 * Mywindow->BorderBottom),
  161.                GA_RelRight, -(Mywindow->BorderRight - 1),
  162.                GA_Height, Mywindow->BorderBottom,
  163.                GA_Width, Mywindow->BorderRight,
  164.                GA_Image, down_image,
  165.                GA_RightBorder, TRUE,
  166.                GA_Previous, up_object,
  167.                ICA_MAP, down2text,
  168.                TAG_END);
  169.  
  170.  
  171. /*
  172.    Clipboard für Textfield öffnen.
  173.    Die Funktion OpenClipboard() kommt aus der iffparse.library.
  174.  */
  175.   clip_handle = OpenClipboard (0);
  176.   undo_handle = OpenClipboard (42);
  177.  
  178. /* Das Textfeld ... */
  179.  
  180.   txtfld = NewObject (TextFieldClass, NULL,
  181.               GA_ID, 1,
  182.         GA_Top, Mywindow->BorderTop + 2 * gap_h + infobar_h + box_h,
  183.               GA_Left, Mywindow->BorderLeft + gap_w,
  184.    GA_RelWidth, -(Mywindow->BorderLeft + Mywindow->BorderRight + 2 * gap_w),
  185.               GA_RelHeight, -(Mywindow->BorderTop + Mywindow->BorderBottom + 4 * gap_h + infobar_h + box_h),
  186.               GA_Previous, down_object,
  187.               GA_TabCycle, TRUE,
  188.               ICA_MAP, text2prop,
  189.               ICA_TARGET, prop_object,
  190.               TEXTFIELD_Text, (ULONG) initial_text,
  191.               TEXTFIELD_UserAlign, FALSE,
  192.               TEXTFIELD_ClipStream, clip_handle,
  193.               TEXTFIELD_UndoStream, undo_handle,
  194.               TEXTFIELD_Border, TEXTFIELD_BORDER_NONE,
  195.               TEXTFIELD_BlinkRate, 500000,
  196.               TEXTFIELD_Spacing, 2,
  197.               TEXTFIELD_PassCommand, TRUE,    /* Amiga-Keys weiterleiten an IMsgPort */
  198.               TEXTFIELD_ReadOnly, FALSE,
  199.               TAG_END);
  200.  
  201. /* Tim Stacks BOOPSI ListView - System */
  202.  
  203.   creategad_group ();
  204.   creategad_message ();
  205.  
  206.   okay = FALSE;            /* wichtig */
  207.  
  208.   if (txtfld && prop_object && up_image &&
  209.       down_image && up_object && down_object)    /* BOOPSI! */
  210.     if (gad_group && gad_message)    /* BOOPSI Listview */
  211.       {
  212.     okay = TRUE;
  213.       }
  214.  
  215.   if (okay)            /* d.h. BOOPSI ist 100% perfekt alloziert */
  216.     {
  217.  
  218.       /* BOOPSI-Verknüpfungen bearbeiten, 2nd pass ... */
  219.       /* Hinweis: "SetGadgetAttrsX" ist Kludge. Grund: fieser Maxon-Compiler-Bug in SetGadgetAttrs()! */
  220.  
  221.       /* checks nötig? */
  222.       SetGadgetAttrsX (prop_object, Mywindow, NULL, ICA_TARGET, txtfld, TAG_DONE);
  223.       SetGadgetAttrsX (up_object, Mywindow, NULL, ICA_TARGET, txtfld, TAG_DONE);
  224.       SetGadgetAttrsX (down_object, Mywindow, NULL, ICA_TARGET, txtfld, TAG_DONE);
  225.  
  226.       /* BOOPSI Listview */
  227.  
  228.       SetGadgetAttrsX (gad_group, Mywindow, NULL, ILGA_Lock, TRUE, TAG_DONE);
  229.       SetGadgetAttrsX (gad_message, Mywindow, NULL, ILGA_Lock, TRUE, TAG_DONE);
  230.  
  231.       AddGList (Mywindow, prop_object, -1, -1, NULL);
  232.       RefreshGadgets (Mywindow->FirstGadget, Mywindow, NULL);
  233.  
  234.       /* Textfield aktivieren */
  235.       ActivateGadget (txtfld, Mywindow, NULL);
  236.  
  237.       /* Bestimme Breite und Offset der Gadgets. */
  238.       /* die Gadgetliste des aktuellen Fensters wird durchsucht ... */
  239.  
  240.       rp = win->RPort;
  241.  
  242.       x = 8;            /* falls kein CloseGadget vorhanden: defaultwert für x (s.u. for()) */
  243.       w = 30;
  244.       h = rp->TxHeight + 3;    /* Gadgethöhe: Texthöhe */
  245.  
  246. /* GadgetTop, von Window-Bottom aus gemesssen (in Pixel): */
  247.       y = -(h + win->BorderBottom + 3);
  248.  
  249. /* todo Abstand RelBottom */
  250.  
  251.       label = "mnNM";
  252.       wspace = TextLength (rp, label, strlen (label));
  253.  
  254.       label = "Nächste";
  255.       w = wspace + TextLength (rp, label, strlen (label));
  256.  
  257.       gads[GID_Naechste] = NewObject (NULL, buttonClassName,
  258.                       GA_RelBottom, y,    /* Abstand von unten */
  259.                       GA_Left, x,
  260.                       GA_Width, w,
  261.                       GA_Height, h,
  262.                       GA_BottomBorder, TRUE,
  263.                       GA_Immediate, TRUE,
  264.                       GA_RelVerify, TRUE,
  265.                       GA_ID, GID_Naechste,
  266.                       GA_Text, label,
  267.                  GA_UserData, (APTR) (DISPLAY_NEXT_MESSAGE),
  268.                       TAG_DONE);
  269.  
  270.       x += w + 2;
  271.       label = "Vorherige";
  272.       w = wspace + TextLength (rp, label, strlen (label));
  273.       gads[GID_Vorherige] = NewObject (NULL, buttonClassName,
  274.                        GA_Previous, gads[GID_Vorherige - 1],
  275.                        GA_RelBottom, y,        /* Abstand von unten */
  276.                        GA_Left, x,
  277.                        GA_Width, w,
  278.                        GA_Height, h,
  279.                        GA_BottomBorder, TRUE,
  280.                        GA_Immediate, TRUE,
  281.                        GA_RelVerify, TRUE,
  282.                        GA_ID, GID_Vorherige,
  283.                        GA_Text, label,
  284.                  GA_UserData, (APTR) (DISPLAY_PREV_MESSAGE),
  285.                        TAG_DONE);
  286.  
  287.       x += w + 2;
  288.       label = "Bugliste zeigen";
  289.       w = wspace + TextLength (rp, label, strlen (label));
  290.       gads[GID_Messages] = NewObject (NULL, buttonClassName,
  291.                       GA_Previous, gads[GID_Messages - 1],
  292.                       GA_RelBottom, y,    /* Abstand von unten */
  293.                       GA_Left, x,
  294.                       GA_Width, w,
  295.                       GA_Height, h,
  296.                       GA_BottomBorder, TRUE,
  297.                       GA_Immediate, TRUE,
  298.                       GA_RelVerify, TRUE,
  299.                       GA_ID, GID_Messages,
  300.                       GA_Text, label,
  301.                       GA_UserData, (APTR) (DISPLAY_BUGS),
  302.                       TAG_DONE);
  303.  
  304.  
  305.       x += w + 2;
  306.       label = "Messagebase scannen";
  307.       w = wspace + TextLength (rp, label, strlen (label));
  308.  
  309.       gads[GID_Gruppen] = NewObject (NULL, buttonClassName,
  310.                      GA_Previous, gads[GID_Gruppen - 1],
  311.                      GA_RelBottom, y,    /* Abstand von unten */
  312.                      GA_Left, x,
  313.                      GA_Width, w,
  314.                      GA_Height, h,
  315.                      GA_BottomBorder, TRUE,
  316.                      GA_Immediate, TRUE,
  317.                      GA_RelVerify, TRUE,
  318.                      GA_ID, GID_Gruppen,
  319.                      GA_Text, label,
  320.                      GA_UserData, (APTR) (GET_NEW_GROUP),
  321.                      TAG_DONE);
  322.  
  323.       x += w + 2;
  324.       label = "Catch Up";
  325.       w = wspace + TextLength (rp, label, strlen (label));
  326.  
  327.       gads[GID_CatchUp] = NewObject (NULL, buttonClassName,
  328.                      GA_Previous, gads[GID_CatchUp - 1],
  329.                      GA_RelBottom, y,    /* Abstand von unten */
  330.                      GA_Left, x,
  331.                      GA_Width, w,
  332.                      GA_Height, h,
  333.                      GA_BottomBorder, TRUE,
  334.                      GA_Immediate, TRUE,
  335.                      GA_RelVerify, TRUE,
  336.                      GA_ID, GID_CatchUp,
  337.                      GA_Text, label,
  338.                 GA_UserData, (APTR) (CATCHUP_CURRENT_GROUP),
  339.                      TAG_DONE);
  340.  
  341.       x += w + 2;
  342.       label = "Guide Hilfe";
  343.       w = wspace + TextLength (rp, label, strlen (label));
  344.  
  345.       gads[GID_Hilfe] = NewObject (NULL, buttonClassName,
  346.                    GA_Previous, gads[GID_Hilfe - 1],
  347.                    GA_RelBottom, y,    /* Abstand von unten */
  348.                    GA_Left, x,
  349.                    GA_Width, w,
  350.                    GA_Height, h,
  351.                    GA_BottomBorder, TRUE,
  352.                    GA_Immediate, TRUE,
  353.                    GA_RelVerify, TRUE,
  354.  
  355.                    GA_ID, GID_Hilfe,
  356.                    GA_Text, label,
  357.                    GA_UserData, (APTR) (OPEN_AMIGAGUIDE),
  358.                    TAG_DONE);
  359.  
  360.       /* Add and refresh the gadget list */
  361.       AddGList (win, gads[0], 0, -1, NULL);
  362.       RefreshGList (gads[0], win, NULL, -1);
  363.     }
  364. }
  365.  
  366. /*
  367.  * selectgad -- Gadget (z.B. nach Tastendruck) als selektiert markieren
  368.  *
  369.  */
  370.  
  371. static void
  372. selectgad (struct Window *win, UWORD sel, BOOL leave)
  373. {
  374.   register int i;
  375.  
  376.   for (i = 0; i < NUMGADS; i++)
  377.     {
  378.       if ((i != sel) || ((i == sel) && leave))
  379.     {
  380.       if (!((i == sel) && (gads[i]->Flags & GFLG_SELECTED)))
  381.         SetGadgetAttrsX (gads[i], win, NULL, GA_Selected, (i == sel), TAG_DONE);
  382.     }
  383.     }
  384. }
  385.  
  386. /*
  387.  * deletegads-- Gadgets entfernen
  388.  */
  389.  
  390. static void
  391. deletegads (struct Window *win)
  392. {
  393.   register int i;
  394.  
  395.   /* alle Gadgets entfernen */
  396.   RemoveGList (Mywindow, Mywindow->FirstGadget, -1);    /* Speicherleck, todo: alle Gadgets entfernen! */
  397.  
  398.   /* BOOPSI Scroller und Textfield */
  399.   DisposeObject (txtfld);    /* safe with Null? :-) */
  400.   DisposeObject (down_object);
  401.   DisposeObject (up_object);
  402.   DisposeObject (down_image);
  403.   DisposeObject (up_image);
  404.   DisposeObject (prop_object);
  405.  
  406.   /* Listview-Gadgets */
  407.   DisposeObject (gad_group);
  408.   DisposeObject (gad_message);
  409.  
  410.   /* Clipboard Handler schließen */
  411.   if (undo_handle)
  412.     {
  413.       CloseClipboard (undo_handle);
  414.     }
  415.  
  416.   if (clip_handle)
  417.     {
  418.       CloseClipboard (clip_handle);
  419.     }
  420.  
  421.   /* DrawInfo Struktur freimachen */
  422.   if (dri)
  423.     {
  424.       FreeScreenDrawInfo (Mywindow->WScreen, dri);
  425.     }
  426.  
  427.   /* BOOPSI Buttons freimachen */
  428.   for (i = 0; i < NUMGADS; i++)
  429.     {
  430.       if (gads[i])
  431.     {
  432.       RemoveGList (win, gads[i], 1);
  433.       DisposeObject (gads[i]);
  434.     }
  435.       else
  436.     printf ("Fehler: Gadget = NULL abgefangen!");
  437.     }
  438. }
  439.  
  440. /*
  441.  * creategad_group -- Gruppenlistview erzeugen
  442.  */
  443.  
  444. static LONG itemlisttags[] =
  445. {ILGA_Selected, 0,
  446.  ILGA_NumSelectable, NS_ONE,
  447.  ILGA_Top, 0,
  448.  ILGA_NoCareShift, TRUE,
  449.  ILGA_HitTest, TRUE,
  450.  TAG_DONE};
  451.  
  452. #define LV_Width 220
  453.  
  454. void 
  455. creategad_group (void)
  456. {
  457.   gad_group = NewObject (NULL, "compoundlistviewgadget",
  458.              GA_Top, Mywindow->BorderTop + gap_h + infobar_h,
  459.              GA_Left, Mywindow->BorderLeft + gap_w,
  460.              GA_Width, LV_Width,
  461.              GA_Height, box_h,
  462.              GA_ID, LV_GROUP,
  463.              GA_Immediate, TRUE,
  464.              GA_RelVerify, TRUE,
  465.              CLV_ILTags, &itemlisttags,
  466.              CLV_DrawInfo, dri,
  467.              TAG_DONE);
  468.   if (gad_group)
  469.     {
  470.       AddGadget (Mywindow, gad_group, -1);
  471.       RefreshGadgets (Mywindow->FirstGadget, Mywindow, NULL);
  472.     }
  473.   else
  474.     ShowError ("gad_group nicht erzeugt");
  475. }
  476.  
  477. void 
  478. creategad_message (void)
  479. {
  480.   gad_message = NewObject (NULL, "compoundlistviewgadget",
  481.                GA_Top, Mywindow->BorderTop + gap_h + infobar_h,
  482.                GA_Left, Mywindow->BorderLeft + gap_w + ((gad_group) ? (gad_group->Width) : (LV_Width)) + gap_w,
  483.                GA_Width, Mywindow->Width -
  484.                (((gad_group) ? (gad_group->Width) : (LV_Width))
  485.                 + Mywindow->BorderLeft
  486.                 + Mywindow->BorderRight + 3 * gap_w),
  487.                GA_Height, box_h,
  488.                GA_ID, LV_MESSAGE,
  489.                GA_Immediate, TRUE,
  490.                GA_RelVerify, TRUE,
  491.                CLV_ILTags, &itemlisttags,
  492.                CLV_DrawInfo, dri,
  493.                TAG_DONE);
  494.  
  495.   if (gad_message)
  496.     {
  497.       AddGadget (Mywindow, gad_message, -1);
  498.       RefreshGadgets (Mywindow->FirstGadget, Mywindow, NULL);
  499.     }
  500.   else
  501.     ShowError ("gad_message nicht erzeugt");
  502. }
  503.